package com.example.parkingproject.service.serviceImp;

import com.alibaba.fastjson.JSON;
import com.example.parkingproject.code.ServiceCode;
import com.example.parkingproject.ex.ServiceException;
import com.example.parkingproject.jopo.dto.AddAdminUserDto;
import com.example.parkingproject.jopo.dto.AdminLoginDto;
import com.example.parkingproject.jopo.dto.UpdateAdminUserDto;
import com.example.parkingproject.jopo.entity.AdminUser;
import com.example.parkingproject.jopo.vo.AdminUserVo;
import com.example.parkingproject.mapper.AdminMapper;
import com.example.parkingproject.security.AdminDetails;
import com.example.parkingproject.service.AdminService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class AdminServiceImp implements AdminService {
    @Autowired
    AdminMapper adminMapper;
    @Value("${parkingproject.jwt.secret-key}")
    private String secretKey;
    @Value("${parkingproject.jwt.duration-in-minute}")
    private Long durationInMinute;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 处理添加管理员用户信息
     *
     * @param addAdminUserDto
     */
    @Override
    public void AddAdminUser(AddAdminUserDto addAdminUserDto) {
        log.debug("传入参数{}", addAdminUserDto);
        AdminUserVo adminUserVo = adminMapper.getAdminUserByCardId(addAdminUserDto.getCardId());
        if (adminUserVo != null) {
            String message = "该管理员已经存在";
            throw new ServiceException(ServiceCode.IS_EXISTENCE, message);
        }
        AdminUser adminUser = new AdminUser();
        BeanUtils.copyProperties(addAdminUserDto, adminUser);
        String password = adminUser.getPassword();
        String encode = passwordEncoder.encode(password);
        adminUser.setPassword(encode);
        log.debug("添加参数{}", adminUser);
        adminUser.setCreateTime(new Date());
        adminMapper.AddAdminUser(adminUser);
    }

    /**
     * 获取管理员用户集合
     *
     * @return
     */
    @Override
    public List<AdminUserVo> AdminList() {
        log.debug("开始处理管查询理员用户集合");
        List<AdminUserVo> list = adminMapper.AdminList();
        return list;
    }

    /**
     * 获取单个管理员用户信息
     *
     * @param cardId
     * @return
     */
    @Override
    public AdminUserVo getAdminByCard(String cardId) {
        log.debug("开始处理参数{}", cardId);
        AdminUserVo adminUserVo = adminMapper.getAdminByCard(cardId);
        log.debug("获取到的用户信息参数{}", adminUserVo);
        return adminUserVo;
    }

    /**
     * 对管理员用户信息进行更改操作
     *
     * @param updateAdminUserDto
     */
    @Override
    public void updateAdminAll(UpdateAdminUserDto updateAdminUserDto) {
        log.debug("处理传入参数{}", updateAdminUserDto);
        adminMapper.updateAdminAll(updateAdminUserDto);
    }

    /**
     * 对管理员用户进行逻辑删除
     *
     * @param cardId
     */
    @Override
    public void deleteAdmin(String cardId) {
        log.debug("传入参数{}", cardId);
        AdminUserVo adminUserByCardId = adminMapper.getAdminUserByCardId(cardId);
        if (adminUserByCardId == null) {
            String message = "删除的用户不存在，请查证";
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, message);
        }
        adminMapper.deleteAdmin(cardId);
    }

    @Override
    public String login(AdminLoginDto adminLoginDto) {
        log.debug("开始处理【管理员登录】的业务，参数：{}", adminLoginDto);
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                adminLoginDto.getUsername(), adminLoginDto.getPassword());

        log.debug("authentication内容:{}", authentication);
        Authentication authenticateResult
                = authenticationManager.authenticate(authentication);
        log.debug("认证通过！（如果未通过，过程中将抛出异常，你不会看到此条日志！）");
        log.debug("认证结果：{}", authenticateResult);
        log.debug("认证结果中的当事人：{}", authenticateResult.getPrincipal());


        // 需要存入到JWT中的数据
        AdminDetails adminDetails = (AdminDetails) authenticateResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", adminDetails.getId());
        claims.put("username", adminDetails.getUsername());
        String authoritiesJsonString = JSON.toJSONString(adminDetails.getAuthorities());
        claims.put("authoritiesJsonString", authoritiesJsonString);

        // 生成JWT，以下代码是相对固定的
        String jwt = Jwts.builder()
                // Header：声明算法与Token类型
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload：数据，具体表现为Claims
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + durationInMinute * 24 * 60 * 60 * 1000))
                // Verify Signature：验证签名
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成了JWT数据：{}", jwt);
        return jwt;
    }

    @Override
    public List<AdminUserVo> search(AddAdminUserDto addAdminUserDto) {
        log.debug("传入参数{}",addAdminUserDto);
        List<AdminUserVo> list = adminMapper.search(addAdminUserDto);
        if (list.size()==0){
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND,"查询的数据不存在");
        }
        return list;
    }

    @Override
    public void setEnable(Integer id) {
            updateEnableById(id,1);
    }

    @Override
    public void setDisable(Integer id) {
            updateEnableById(id,0);
    }

    private void updateEnableById(Integer id,Integer enable) {
        AdminUserVo adminById = adminMapper.getAdminById(id);
        if (adminById == null) {
            throw new ServiceException(ServiceCode.ERROR_NOT_FOUND, "数据不存在");
        }
        if (enable.equals(adminById.getPermissions())) {
            String message =  "失败,修改的目标状态与目前一致";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERROR_CONFLICT, message);
        }
        AdminUserVo adminUserVo = new AdminUserVo();
        adminUserVo.setId(id);
        adminUserVo.setPermissions(enable);

        Integer rows = adminMapper.changePermission(adminUserVo);
        if (rows != 1) {
            String message = "失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.error_bad_request, message);
        }
    }
}
